import tkinter as tk
from tkinter import ttk, filedialog, messagebox, scrolledtext
import os
import fitz  # PyMuPDF
from PIL import Image
import threading

class PDFToImageConverter:
    def __init__(self, root):
        self.root = root
        self.root.title("PDF转图片转换器")
        self.root.geometry("600x500")
        
        self.pdf_path = ""
        self.output_dir = ""
        self.setup_ui()
    
    def setup_ui(self):
        # 主框架
        main_frame = ttk.Frame(self.root, padding="15")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 文件选择区域
        file_frame = ttk.LabelFrame(main_frame, text="PDF文件选择", padding="10")
        file_frame.grid(row=0, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10))
        
        self.file_path = tk.StringVar()
        ttk.Label(file_frame, text="PDF文件路径:").grid(row=0, column=0, sticky=tk.W)
        ttk.Entry(file_frame, textvariable=self.file_path, width=60).grid(row=1, column=0, sticky=(tk.W, tk.E), padx=(0, 10))
        ttk.Button(file_frame, text="浏览", command=self.browse_file).grid(row=1, column=1)
        
        # 输出设置区域
        output_frame = ttk.LabelFrame(main_frame, text="输出设置", padding="10")
        output_frame.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10))
        
        ttk.Label(output_frame, text="输出目录:").grid(row=0, column=0, sticky=tk.W)
        self.output_path = tk.StringVar()
        ttk.Entry(output_frame, textvariable=self.output_path, width=50).grid(row=1, column=0, sticky=(tk.W, tk.E), padx=(0, 10))
        ttk.Button(output_frame, text="选择目录", command=self.browse_output_dir).grid(row=1, column=1)
        
        # 图片格式选择
        format_frame = ttk.Frame(output_frame)
        format_frame.grid(row=2, column=0, columnspan=2, sticky=tk.W, pady=(10, 0))
        
        ttk.Label(format_frame, text="图片格式:").grid(row=0, column=0, sticky=tk.W)
        self.format_var = tk.StringVar(value="PNG")
        formats = [("PNG", "PNG"), ("JPEG", "JPEG"), ("BMP", "BMP"), ("TIFF", "TIFF")]
        for i, (text, value) in enumerate(formats):
            ttk.Radiobutton(format_frame, text=text, variable=self.format_var, value=value).grid(row=0, column=i+1, padx=(10, 0))
        
        # 分辨率设置
        resolution_frame = ttk.Frame(output_frame)
        resolution_frame.grid(row=3, column=0, columnspan=2, sticky=tk.W, pady=(10, 0))
        
        ttk.Label(resolution_frame, text="分辨率(DPI):").grid(row=0, column=0, sticky=tk.W)
        self.dpi_var = tk.StringVar(value="150")
        dpi_options = ["72", "150", "200", "300"]
        ttk.Combobox(resolution_frame, textvariable=self.dpi_var, values=dpi_options, width=10).grid(row=0, column=1, padx=(10, 0))
        
        # 转换按钮
        button_frame = ttk.Frame(main_frame)
        button_frame.grid(row=2, column=0, columnspan=2, pady=10)
        
        ttk.Button(button_frame, text="开始转换", command=self.start_conversion).grid(row=0, column=0, padx=(0, 10))
        ttk.Button(button_frame, text="清空日志", command=self.clear_log).grid(row=0, column=1)
        
        # 进度条
        self.progress = ttk.Progressbar(main_frame, mode='determinate')
        self.progress.grid(row=3, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10))
        
        # 日志区域
        log_frame = ttk.LabelFrame(main_frame, text="转换日志", padding="10")
        log_frame.grid(row=4, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        self.log_text = scrolledtext.ScrolledText(log_frame, height=15, width=70)
        self.log_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 配置权重
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=1)
        main_frame.columnconfigure(0, weight=1)
        main_frame.rowconfigure(4, weight=1)
        file_frame.columnconfigure(0, weight=1)
        output_frame.columnconfigure(0, weight=1)
        log_frame.columnconfigure(0, weight=1)
        log_frame.rowconfigure(0, weight=1)
    
    def browse_file(self):
        filetypes = [
            ("PDF文档", "*.pdf"),
            ("所有文件", "*.*")
        ]
        filename = filedialog.askopenfilename(
            title="选择PDF文档",
            filetypes=filetypes
        )
        if filename:
            self.file_path.set(filename)
            # 自动设置输出目录为PDF文件所在目录
            pdf_dir = os.path.dirname(filename)
            pdf_name = os.path.splitext(os.path.basename(filename))[0]
            default_output = os.path.join(pdf_dir, f"{pdf_name}_images")
            self.output_path.set(default_output)
            self.log(f"已选择PDF文件: {filename}")
    
    def browse_output_dir(self):
        directory = filedialog.askdirectory(title="选择输出目录")
        if directory:
            self.output_path.set(directory)
            self.log(f"输出目录设置为: {directory}")
    
    def log(self, message):
        self.log_text.insert(tk.END, f"{message}\n")
        self.log_text.see(tk.END)
        self.root.update_idletasks()
    
    def clear_log(self):
        self.log_text.delete(1.0, tk.END)
    
    def start_conversion(self):
        if not self.file_path.get():
            messagebox.showerror("错误", "请先选择PDF文件")
            return
        
        if not self.output_path.get():
            messagebox.showerror("错误", "请选择输出目录")
            return
        
        # 在新线程中执行转换，避免界面卡顿
        thread = threading.Thread(target=self.convert_pdf_to_images)
        thread.daemon = True
        thread.start()
    
    def convert_pdf_to_images(self):
        try:
            pdf_path = self.file_path.get()
            output_dir = self.output_path.get()
            img_format = self.format_var.get()
            dpi = int(self.dpi_var.get())
            
            # 创建输出目录
            if not os.path.exists(output_dir):
                os.makedirs(output_dir)
            
            self.log(f"开始转换PDF: {os.path.basename(pdf_path)}")
            self.log(f"输出目录: {output_dir}")
            self.log(f"图片格式: {img_format}, DPI: {dpi}")
            
            # 打开PDF文件
            pdf_document = fitz.open(pdf_path)
            total_pages = len(pdf_document)
            
            self.log(f"PDF总页数: {total_pages}")
            
            # 设置进度条最大值
            self.progress["maximum"] = total_pages
            self.progress["value"] = 0
            
            # 逐页转换
            for page_num in range(total_pages):
                page = pdf_document[page_num]
                
                # 设置转换矩阵（分辨率）
                mat = fitz.Matrix(dpi/72, dpi/72)  # 72是默认DPI
                pix = page.get_pixmap(matrix=mat)
                
                # 生成输出文件名
                img_filename = f"page_{page_num+1:03d}.{img_format.lower()}"
                img_path = os.path.join(output_dir, img_filename)
                
                # 保存图片
                if img_format == "JPEG":
                    pix.save(img_path, "JPEG", quality=95)
                else:
                    pix.save(img_path)
                
                self.log(f"已转换第 {page_num+1} 页 -> {img_filename}")
                
                # 更新进度条
                self.progress["value"] = page_num + 1
                self.root.update_idletasks()
            
            pdf_document.close()
            
            self.log("转换完成!")
            messagebox.showinfo("成功", f"PDF已成功转换为图片!\n共转换 {total_pages} 页\n输出目录: {output_dir}")
            
        except Exception as e:
            self.log(f"转换失败: {str(e)}")
            messagebox.showerror("错误", f"转换过程中出现错误:\n{str(e)}")
        
        finally:
            # 重置进度条
            self.progress["value"] = 0

def main():
    root = tk.Tk()
    app = PDFToImageConverter(root)
    root.mainloop()

if __name__ == "__main__":
    main()